package com.oracle.coherence.patterns.security.management.rmi;

import com.oracle.coherence.patterns.security.KrbSecurityHelper;
import com.tangosol.util.Base;

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;

/**
 * An extension of the {@link javax.management.remote.rmi.RMIConnector} class
 * that allows JMX clients to connect to a JMX server that requires
 * Kerberos type security credentials.
 * <p/>
 *
 * @author Jonathan Knight
 */
public class KrbRMIConnector extends RMIConnector {

    public KrbRMIConnector(JMXServiceURL url, Map<String, ?> environment) {
        super(url, environment);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void connect(Map<String, ?> environment) throws IOException {
        final Map<String, Object> jmxEnv = new HashMap<String, Object>();

        if (environment != null) {
            jmxEnv.putAll(environment);
        }

        try {
            Subject subject = KrbSecurityHelper.login();
            jmxEnv.put(JMXConnector.CREDENTIALS, subject);

            Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
                @Override
                public Object run() throws Exception {
                    KrbRMIConnector.super.connect(jmxEnv);
                    return null;
                }
            });
        } catch (LoginException e) {
            throw Base.ensureRuntimeException(e);
        } catch (PrivilegedActionException e) {
            e.printStackTrace();
        }
    }
}
